#include "EpilTableConstructorParser.h"
#include "EpilParserException.h"
#include "EpilListFieldParser.h"
#include "EpilRecordFieldParser.h"
#include "EpilPointerHelper.h"


EpilTableConstructorParser::EpilTableConstructorParser( EpilTokenStream & tokens )
: EpilSyntaxParserBase( tokens )
{
}


void EpilTableConstructorParser::Parse()
{
	// constructor -> ??, WTF?!
	if( this->GetTokens().GetCurrentToken().type != ETT_OpenBrace )
	{
		throw EpilParserException( t("\'{\' expected."), this->GetTokens().GetCurrentToken().location );
	}

	m_constructor = new EpilTableConstructorExpressionCode( this->GetTokens().GetCurrentToken().location );
	this->GetTokens().MoveToNext();

	for(;;)
	{
		if( this->GetTokens().GetCurrentToken().type == ETT_CloseBrace )
		{
			break;
		}

		switch( this->GetTokens().GetCurrentToken().type )
		{
		case ETT_Identifier:
			{
				if( this->GetTokens().PeekNextToken().type != ETT_OpAssign )
				{
					EpilListFieldParser listFieldParser( this->GetTokens() );
					try
					{
						listFieldParser.Parse();
					}
					catch( ... )
					{
						EpilPointerHelper::SafeDelete( m_constructor );
						throw;
					}
					m_constructor->GetInitializers().push_back( listFieldParser.GetInitializer() );
				}
				else
				{
					EpilRecordFieldParser recordFieldParser( this->GetTokens() );
					try
					{
						recordFieldParser.Parse();
					}
					catch( ... )
					{
						EpilPointerHelper::SafeDelete( m_constructor );
						throw;
					}
					m_constructor->GetInitializers().push_back( recordFieldParser.GetInitializer() );
				}
			}
			break;
		case ETT_OpenBracket:
			{
				EpilRecordFieldParser recordFieldParser( this->GetTokens() );
				try
				{
					recordFieldParser.Parse();
				}
				catch( ... )
				{
					EpilPointerHelper::SafeDelete( m_constructor );
					throw;
				}
				m_constructor->GetInitializers().push_back( recordFieldParser.GetInitializer() );
			}
			break;
		default:
			{
				EpilListFieldParser listFieldParser( this->GetTokens() );
				try
				{
					listFieldParser.Parse();
				}
				catch( ... )
				{
					EpilPointerHelper::SafeDelete( m_constructor );
					throw;
				}
				m_constructor->GetInitializers().push_back( listFieldParser.GetInitializer() );
			}
			break;
		}

		if( this->GetTokens().GetCurrentToken().type != ETT_OpComma &&
			this->GetTokens().GetCurrentToken().type != ETT_OpSemicolon )
		{
			break;
		}
		this->GetTokens().MoveToNext();
	}

	if( this->GetTokens().GetCurrentToken().type != ETT_CloseBrace )
	{
		EpilPointerHelper::SafeDelete( m_constructor );
		throw EpilParserException( t("\'}\' expected."), this->GetTokens().GetCurrentToken().location );
	}
	this->GetTokens().MoveToNext();
}